package main

import (
	"bufio"
	"fmt"
	"log"
	"mini-sql/config"
	"mini-sql/executor"
	"mini-sql/storage"
	"mini-sql/utils"
	"os"
	"strings"
)

func main() {
	fmt.Println("mini-sql command line tools")
	executor := executor.NewExecutor()
	executor.StorePool = storage.NewStorePool()

	for {
		fmt.Printf(">>> ")
		reader := bufio.NewReader(os.Stdin)
		line, err := reader.ReadString('\n')
		if err != nil {
			log.Printf("read from stdio failed, err=%v", err)
			return
		}

		line = strings.TrimRight(line, "\r\n")
		if line == "exit" || line == "quit" {
			break
		}

		handleInputLine(line, executor)
	}
}

func handleInputLine(line string, executor *executor.Executor) {
	if line == "" {
		fmt.Println("input is empty, please retry")
		return
	}

	parts := strings.Fields(line)
	cmd := strings.ToLower(parts[0])

	switch cmd {
	case "set":
		handleSetConfigCmd(parts)
		return
	case "memory":
		handleMemoryCmd(executor, parts)
	default:
		{
			err := executor.ExecuteSQL(line)
			if err != nil {
				log.Printf("ExecuteSQL failed, err:%v", err)
			}
		}
	}
}

func handleSetConfigCmd(parts []string) {
	if len(parts) != 3 {
		fmt.Printf("wrong set command, set <name> <value>\n")
		return
	}
	name := parts[1]
	value := parts[2]

	switch name {
	case "DebugParsing":
		config.DebugParsing = utils.ParseBoolIgnoreError(value)
	case "DebugExecutor":
		config.DebugExecutor = utils.ParseBoolIgnoreError(value)
	case "PrintAstTree":
		config.PrintAstTree = utils.ParseBoolIgnoreError(value)
	case "PrintAntlrTree":
		config.PrintAntlrTree = utils.ParseBoolIgnoreError(value)
	default:
		fmt.Printf("unknown config name: %v\n", name)
		return
	}

	fmt.Println("set config done")
}

func handleMemoryCmd(executor *executor.Executor, parts []string) {
	pool := executor.StorePool

	for tableName, tableInfo := range pool.GetTableMap() {
		stat := tableInfo.GetStat()
		fmt.Printf("table: %v, memUsed: %v\n", tableName, stat.MemUsed)
	}
}
